package org.snia.cdmi.rs.provider;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Map;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;

import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.snia.cdmi.model.Container;

/**
 * <p>JSON Serialization/Deserialization for {@link Container} instances.</p>
 * @author craigmcc
 */
public class ContainerProvider
    extends AbstractProvider
    implements MessageBodyReader<Container>, MessageBodyWriter<Container> {


    // ----------------------------------------------- MessageBodyReader Methods


    @Override
    public boolean isReadable(Class<?> clazz, Type type,
                              Annotation[] annotations, MediaType mediaType) {
        return Container.class.isAssignableFrom(clazz);
    }

    @Override
    public Container readFrom(Class<Container> clazz, Type type,
                              Annotation[] annotations, MediaType mediaType,
                              MultivaluedMap<String, String> headers,
                              InputStream in) throws IOException, WebApplicationException {
        JSONObject entity = convertJSON(in);
        Container container = new Container();
        try {
            Map<String,String> metadata = convertMap(entity.getJSONObject("metadata"));
            container.getUserMetadata().putAll(metadata);
//            Map<String,Object> exports = convertHash(entity.getJSONObject("exports"));
//            container.getExports().putAll(exports);
//            if (entity.has("copy")) {
//                container.setCopy(entity.getString("copy"));
//            }
//            if (entity.has("move")) {
//                container.setMove(entity.getString("move"));
//            }
//            if (entity.has("reference")) {
//                container.setReference(entity.getString("reference"));
//            }
        } catch (JSONException e) {
            throw new IOException(e);
        }
        throw new UnsupportedOperationException("Not supported yet.");
    }


    // ----------------------------------------------- MessageBodyWriter Methods


    @Override
    public boolean isWriteable(Class<?> clazz, Type type,
                               Annotation[] annotations, MediaType mediaType) {
        return Container.class.isAssignableFrom(clazz);
    }

    @Override
    public long getSize(Container entity, Class<?> clazz, Type type,
                        Annotation[] annotations, MediaType mediaTYpe) {
        return -1;
    }

    @Override
    public void writeTo(Container container, Class<?> clazz, Type type,
                        Annotation[] annotations, MediaType mediaType,
                        MultivaluedMap<String, Object> headers, OutputStream out) throws IOException, WebApplicationException {
        JSONObject entity = new JSONObject();
        try {
            Writer writer = new OutputStreamWriter(out);
//            if (container.getObjectURI() != null) {
//                entity.put("objectURI", container.getObjectURI());
//            }
//            if (container.getObjectID() != null) {
//                entity.put("objectID", container.getObjectID());
//            }
//            if (container.getParentURI() != null) {
//                entity.put("parentURI", container.getParentURI());
//            }
//            if (container.getDomainURI() != null) {
//                entity.put("domainURI", container.getDomainURI());
//            }
//            if (container.getCapabilitiesURI() != null) {
//                entity.put("capabilitiesURI", container.getCapabilitiesURI());
//            }
//            if (container.getCompletionStatus() != null) {
//                entity.put("completionStatus", container.getCompletionStatus());
//            }
//            if (container.getPercentComplete() != null) {
//                entity.put("percentComplete", container.getPercentComplete());
//            }
            if (container.getUserMetadata().size() > 0) {
                entity.put("metadata", container.getUserMetadata());
            }
//            if (container.getExports().size() > 0) {
//                entity.put("exports", container.getExports());
//            }
//            if (container.getChildrenrange() != null) {
//                entity.put("childrenrange", container.getChildrenrange());
//            }
//            if (container.getChildren().size() > 0) {
//                entity.put("children", container.getChildren());
//            }
            entity.write(writer);
            writer.flush();
        } catch (JSONException e) {
            throw new IOException(e);
        }
    }


}
